package info.gridworld.grid;

import java.util.ArrayList;

public class UnboundedGrid3<E> extends AbstractGrid<E>  {
    Object[][] occupantArray;
    int size;

    public UnboundedGrid3() {
        this.occupantArray = new Object[16][16];
        this.size = 16;
    }

    @Override
    public int getNumRows() {
        return -1;
    }
    @Override
    public int getNumCols() {
        return -1;
    }

    @Override
    public boolean isValid(Location loc) {
        return 0 <= loc.getRow()  && 0 <= loc.getCol();
    }

    @Override
    public E put(Location loc, E obj) {
        if (!isValid(loc))
            throw new IllegalArgumentException("Location " + loc + " is not valid");
        if (obj == null)
            throw new NullPointerException("obj == null");

        int r = loc.getRow();
        int c = loc.getCol();

        E oldOccupant = this.get(loc);

        Object[][] tmp = this.occupantArray;
        while(this.size<=r || this.size<=c)
            this.size*=2;
        this.occupantArray = new Object[this.size][this.size];
        for (int i = 0; i < tmp.length; i++) {
            for (int j = 0; j < tmp.length; j++)
                occupantArray[i][j] = tmp[i][j];
        }

        occupantArray[r][c] = obj;
        return oldOccupant;
    }

    @Override
    public E remove(Location loc) {
        if (!isValid(loc))
            throw new IllegalArgumentException("Location " + loc + " is not valid");

        E tmp=null;
        if (loc.getRow() < this.size && loc.getCol() < this.size)
            tmp= (E) this.occupantArray[loc.getRow()][loc.getCol()];
            occupantArray[loc.getRow()][loc.getCol()] = null;
        return tmp;
    }

    @Override
    public E get(Location loc) {
        if (!isValid(loc))
            throw new IllegalArgumentException("Location " + loc + " is not valid");

        if (loc.getRow() >= this.size || loc.getCol() >= this.size)
            return null;

        return (E) this.occupantArray[loc.getRow()][loc.getCol()];

    }

    @Override
    public ArrayList<Location> getOccupiedLocations() {
        ArrayList<Location> theLocations = new ArrayList<Location>();

        for (int r = 0; r < this.size; r++)
        {
            for (int c = 0; c < this.size; c++)
            {
                Location loc = new Location(r, c);
                if (get(loc) != null)
                    theLocations.add(loc);
            }
        }
        return theLocations;

    }
}
